package com.zenithmind.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.chat.enums.AddSource;
import com.zenithmind.chat.enums.FriendRequestStatus;
import com.zenithmind.chat.enums.FriendStatus;
import com.zenithmind.chat.mapper.ChatFriendMapper;
import com.zenithmind.chat.mapper.ChatFriendRequestMapper;
import com.zenithmind.chat.pojo.dto.ChatFriendRequestDTO;
import com.zenithmind.chat.pojo.entity.ChatFriend;
import com.zenithmind.chat.pojo.entity.ChatFriendRequest;
import com.zenithmind.chat.pojo.vo.ChatFriendRequestVO;
import com.zenithmind.chat.pojo.vo.ChatFriendRequestStatisticsVO;
import com.zenithmind.chat.service.ChatFriendRequestService;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 好友申请服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatFriendRequestServiceImpl extends ServiceImpl<ChatFriendRequestMapper, ChatFriendRequest>
        implements ChatFriendRequestService {

    private final ChatFriendMapper friendMapper;



    @Override
    public String create(ChatFriendRequestDTO dto, String userId) {
        // TODO: 实现创建好友申请逻辑
        return null;
    }

    @Override
    public PageResult<ChatFriendRequestVO> getFriendRequestPage(String userId, String type, Integer status, 
                                                               Integer pageNum, Integer pageSize) {
        Page<ChatFriendRequest> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status)
               .orderByDesc(ChatFriendRequest::getRequestTime);
        
        IPage<ChatFriendRequest> result = page(page, wrapper);
        
        List<ChatFriendRequestVO> voList = result.getRecords().stream()
            .map(request -> convertToVO(request, userId))
            .collect(Collectors.toList());
        
        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public List<ChatFriendRequestVO> getUserFriendRequests(String userId, String type, Integer status) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status)
               .orderByDesc(ChatFriendRequest::getRequestTime);
        
        List<ChatFriendRequest> requests = list(wrapper);
        
        return requests.stream()
            .map(request -> convertToVO(request, userId))
            .collect(Collectors.toList());
    }

    @Override
    public ChatFriendRequestVO getFriendRequestById(String id, String userId) {
        ChatFriendRequest request = getById(id);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        // 检查权限
        if (!Objects.equals(request.getRequesterId(), userId) && 
            !Objects.equals(request.getTargetId(), userId)) {
            throw new BusinessException("无权限查看该申请");
        }
        
        return convertToVO(request, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean handleFriendRequest(String requestId, Boolean accept, String responseMessage, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }

        // 使用实体的业务方法 - 遵循迪米特法则
        if (!request.canBeHandledBy(userId)) {
            throw new BusinessException("无权限处理该申请");
        }

        if (request.isProcessed()) {
            throw new BusinessException("该申请已被处理");
        }

        if (request.isExpired()) {
            throw new BusinessException("该申请已过期");
        }
        
        // 使用实体的业务方法处理申请 - 遵循迪米特法则
        request.process(accept, responseMessage);
        updateById(request);

        if (accept) {
            // 创建双向好友关系
            createFriendRelation(request.getRequesterId(), request.getTargetId());
        }
        
        log.info("用户 {} {} 好友申请 {}", userId, accept ? "同意" : "拒绝", requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean withdrawFriendRequest(String requestId, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        // 使用实体的业务方法 - 遵循迪米特法则
        if (!request.canBeWithdrawnBy(userId)) {
            throw new BusinessException("无权限撤回该申请或申请已被处理");
        }
        
        // 软删除申请
        removeById(requestId);
        
        log.info("用户 {} 撤回好友申请 {}", userId, requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFriendRequest(String requestId, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        // 检查权限（申请人或目标用户都可以删除）
        if (!Objects.equals(request.getRequesterId(), userId) && 
            !Objects.equals(request.getTargetId(), userId)) {
            throw new BusinessException("无权限删除该申请");
        }
        
        removeById(requestId);
        
        log.info("用户 {} 删除好友申请 {}", userId, requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchHandleFriendRequests(List<String> requestIds, Boolean accept, String userId) {
        if (CollectionUtils.isEmpty(requestIds)) {
            return false;
        }
        
        for (String requestId : requestIds) {
            try {
                handleFriendRequest(requestId, accept, null, userId);
            } catch (Exception e) {
                log.error("批量处理好友申请失败: {}", requestId, e);
            }
        }
        
        return true;
    }

    @Override
    public Integer countFriendRequests(String userId, String type, Integer status) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status);
        
        return Math.toIntExact(count(wrapper));
    }

    @Override
    public Boolean checkRequestExists(String requesterId, String targetId) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatFriendRequest::getRequesterId, requesterId)
               .eq(ChatFriendRequest::getTargetId, targetId)
               .eq(ChatFriendRequest::getStatus, 0); // 待处理
        
        return count(wrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanExpiredRequests(Integer days) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatFriendRequest::getStatus, 0)
               .lt(ChatFriendRequest::getExpireTime, expireTime);
        
        List<ChatFriendRequest> expiredRequests = list(wrapper);
        
        if (!CollectionUtils.isEmpty(expiredRequests)) {
            // 更新状态为过期
            expiredRequests.forEach(request -> request.setStatus(FriendRequestStatus.EXPIRED));
            updateBatchById(expiredRequests);
        }
        
        return expiredRequests.size();
    }

    @Override
    public ChatFriendRequestStatisticsVO getRequestStatistics(String userId, String startTime, String endTime) {
        // 基础查询条件
        LambdaQueryWrapper<ChatFriendRequest> baseWrapper = new LambdaQueryWrapper<>();

        if (StringUtils.hasText(userId)) {
            baseWrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                                 .or()
                                 .eq(ChatFriendRequest::getTargetId, userId));
        }

        // 统计各种状态的申请数量
        long total = count(baseWrapper);

        // 待处理
        LambdaQueryWrapper<ChatFriendRequest> pendingWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(userId)) {
            pendingWrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                                   .or()
                                   .eq(ChatFriendRequest::getTargetId, userId));
        }
        pendingWrapper.eq(ChatFriendRequest::getStatus, FriendRequestStatus.PENDING);
        long pending = count(pendingWrapper);

        // 已同意
        LambdaQueryWrapper<ChatFriendRequest> acceptedWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(userId)) {
            acceptedWrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                                    .or()
                                    .eq(ChatFriendRequest::getTargetId, userId));
        }
        acceptedWrapper.eq(ChatFriendRequest::getStatus, FriendRequestStatus.ACCEPTED);
        long accepted = count(acceptedWrapper);

        // 已拒绝
        LambdaQueryWrapper<ChatFriendRequest> rejectedWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(userId)) {
            rejectedWrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                                    .or()
                                    .eq(ChatFriendRequest::getTargetId, userId));
        }
        rejectedWrapper.eq(ChatFriendRequest::getStatus, FriendRequestStatus.REJECTED);
        long rejected = count(rejectedWrapper);

        // 已过期
        LambdaQueryWrapper<ChatFriendRequest> expiredWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(userId)) {
            expiredWrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                                   .or()
                                   .eq(ChatFriendRequest::getTargetId, userId));
        }
        expiredWrapper.eq(ChatFriendRequest::getStatus, FriendRequestStatus.EXPIRED);
        long expired = count(expiredWrapper);

        return new ChatFriendRequestStatisticsVO(total, pending, accepted, rejected, expired);
    }

    /**
     * 转换为VO对象 - 遵循单一职责原则
     */
    private ChatFriendRequestVO convertToVO(ChatFriendRequest request, String userId) {
        ChatFriendRequestVO vo = new ChatFriendRequestVO();

        // 手动复制基本属性，避免使用已弃用的BeanCopyUtils
        vo.setId(request.getId());
        vo.setRequesterId(request.getRequesterId());
        vo.setTargetId(request.getTargetId());
        vo.setRequestMessage(request.getRequestMessage());
        vo.setResponseMessage(request.getResponseMessage());
        vo.setRequestTime(request.getRequestTime());
        vo.setResponseTime(request.getResponseTime());
        vo.setExpireTime(request.getExpireTime());

        // 使用枚举的描述 - 遵循开闭原则
        vo.setStatusText(request.getStatus().getDescription());

        // 使用实体的业务方法 - 遵循迪米特法则
        vo.setIsExpired(request.isExpired());
        vo.setCanHandle(request.canBeHandledBy(userId) && !request.isProcessed() && !request.isExpired());

        // 设置申请类型
        vo.setType(Objects.equals(request.getRequesterId(), userId) ? "sent" : "received");

        return vo;
    }

    /**
     * 创建好友关系 - 遵循单一职责原则，只负责创建关系
     */
    private void createFriendRelation(String userId1, String userId2) {
        LocalDateTime now = LocalDateTime.now();
        
        // 创建用户1 -> 用户2的关系
        ChatFriend friend1 = new ChatFriend();
        friend1.setUserId(userId1);
        friend1.setFriendId(userId2);
        // friend1.setFriendName(userName2); // 移除，从用户服务获取
        friend1.setStatus(FriendStatus.NORMAL);
        friend1.setGroupName("我的好友");
        friend1.setAddTime(now);
        friend1.setAddSource(AddSource.FRIEND_REQUEST);
        
        // 创建用户2 -> 用户1的关系
        ChatFriend friend2 = new ChatFriend();
        friend2.setUserId(userId2);
        friend2.setFriendId(userId1);
        // friend2.setFriendName(userName1); // 移除，从用户服务获取
        friend2.setStatus(FriendStatus.NORMAL);
        friend2.setGroupName("我的好友");
        friend2.setAddTime(now);
        friend2.setAddSource(AddSource.FRIEND_REQUEST);
        
        friendMapper.insert(friend1);
        friendMapper.insert(friend2);
    }
}
